package cn.edu.laud.sany.datatest;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;

import oracle.net.aso.l;

import cn.edu.laud.sany.types.ImportProcess;
import cn.edu.laud.sany.types.RowData;
import cn.edu.laud.sany.types.TimeSerial;
import cn.edu.laud.sany.utils.Config;
import cn.edu.laud.sany.utils.MyLog;
import cn.edu.laud.sany.utils.ProcessManager;

public class ScanDataTest
{
	public static Integer[] cFS;
	public static HashSet<Integer> ignoreParaIds = new HashSet<Integer>();
	public static String csvFolder = "";
	public static String cfsFile = "";
	public static String logFileFolder = "log";
	public static String logFileName = "mylogtest.txt";
	
	public static long allReadCount = 0;
	public static long allIgnoreCount = 0;
	public static long errorCount = 0;
	
	public static HashMap<Integer, HashMap<String, Long>> allDataCount;
	public static HashSet<String> equipSet;
	
	public static BufferedWriter writer1;
	public static BufferedWriter writer2;
	
	private static MyLog logger;
	
	/**
	 * @param args
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	public static void main(String[] args) throws ClassNotFoundException, SQLException, IOException
	{
		initLaUDMyLog();
		doMain(args);
	}
	
	public static String getLogFilePath()
	{
		return (logFileFolder + "/" + logFileName);
	}
	
	protected static void initLaUDMyLog()
	{
		File logFolderFile = new File(logFileFolder);
		if (logFolderFile.exists() == false)
		{
			logFolderFile.mkdir();
		}
		logger = MyLog.getMyLog(getLogFilePath(), true);
	}
	
	protected static void doMain(String[] args) throws ClassNotFoundException, SQLException,
			IOException
	{
		if (args.length % 2 == 1 || args.length < 1)
		{
			System.err.println(Config.CommandHelpString);
			return;
		}
		
		try
		{
			parseParams(args);
		}
		catch (Exception e)
		{
			System.err.println(Config.CommandHelpString);
			return;
		}
		
		try
		{
			writer1 = new BufferedWriter(new FileWriter(new File("result1.txt")));
			writer2 = new BufferedWriter(new FileWriter(new File("result2.csv")));
		}
		catch (IOException e2)
		{
			e2.printStackTrace();
		}
		allDataCount = new HashMap<Integer, HashMap<String, Long>>();
		equipSet = new HashSet<String>();
		
		// test csv and cfs files
		if (testCsvFoler() == false)
		{
			System.err.println("can not find csv folder");
			return;
		}
		if (testCfFile() == false)
		{
			System.err.println("can not find CFs file");
			return;
		}
		if (getCFNames() == false)
		{
			System.err.println("can not read CFs correctly");
			return;
		}
		if (getIgnoreParaIds() == false)
		{
			System.err.println("can read ignoreParaIds correctly");
			return;
		}
		
		long starttime = System.nanoTime();
		logger.info("import test start, time:" + starttime);
		
		try
		{
			ProcessManager.InitProcessManager(logger, csvFolder, logFileFolder, false);
			ProcessManager.writeProgressSpeedlog = false;
			ProcessManager.updateTimesToWriteFile = 2;
		}
		catch (Exception e)
		{
			System.err.println("init ProcessManager failed: " + e.getMessage());
			return;
		}
		
		HashMap<String, ImportProcess> fileProcessMap = ProcessManager.getFileProcessMap();
		ProcessManager.getAvailableSource();
		Iterator<ImportProcess> iter = fileProcessMap.values().iterator();
		while (iter.hasNext())
		{
			ImportProcess val = iter.next();
			File file = new File(val.name);
			if (file.exists() == false)
			{
				logger.info("!File not exist:" + val.name);
				continue;
			}
			BufferedReader bReader = new BufferedReader(new FileReader(file));
			logger.info("read file:" + val.name);
			int nowCount = 1;
			String lineData = bReader.readLine();
			while ((lineData = bReader.readLine()) != null && nowCount < val.count)
			{
				processIgnored(lineData);
				nowCount++;
				allReadCount++;
				if (allReadCount % 1000000 == 0)
				{
					logger.info("read count=" + allReadCount + "  find ignore count="
							+ allIgnoreCount + "  error count=" + errorCount);
				}
			}
			logger.info("read count=" + allReadCount + "  find ignore count=" + allIgnoreCount
					+ "  error count=" + errorCount);
			bReader.close();
		}
		long endTime = System.nanoTime();
		logger.info("read finish, run time:"
				+ cn.edu.laud.sany.utils.TimeUtils.nanoSecondToString((endTime - starttime))
				+ " read count=" + allReadCount + "  find ignore count=" + allIgnoreCount
				+ "  error count=" + errorCount + "  waiting to write result file.");
		try
		{
			printCountTable();
			writer1.flush();
			writer1.close();
			writer2.flush();
			writer2.close();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		endTime = System.nanoTime();
		logger.info("test program's run time:"
				+ cn.edu.laud.sany.utils.TimeUtils.nanoSecondToString((endTime - starttime)));
	}
	
	protected static void printCountTable() throws IOException
	{
		writer2.write("equip,");
		for (int paraId : cFS)
		{
			writer2.write(String.valueOf(paraId));
			writer2.write(",");
		}
		writer2.write("count");
		writer2.write("\r\n");
		for (String equipId : equipSet)
		{
			long count = 0;
			writer2.write(equipId);
			writer2.write(",");
			for (int paraId : cFS)
			{
				long num = 0;
				if (allDataCount.get(paraId).containsKey(equipId))
				{
					num = allDataCount.get(paraId).get(equipId);
					count += num;
					if (num != 0)
					{
						writer1.write(String.valueOf(paraId));
						writer1.write(":");
						writer1.write(equipId);
						writer1.write("=");
						writer1.write(String.valueOf(num));
						writer1.write("\r\n");
						writer1.flush();
					}
				}
				writer2.write(String.valueOf(num));
				writer2.write(",");
			}
			
			writer2.flush();
			writer2.write(String.valueOf(count));
			writer2.write("\r\n");
		}
	}
	
	protected static void processIgnored(String string)
	{
		String data[] = null;
		try
		{
			data = string.split(",");
			if (data.length != 6)
			{
				logger.error("data format error.(org:)" + string);
				allIgnoreCount++;
				errorCount++;
				return;
			}
			String equipCode = trimData(data[1]);
			if (!equipSet.contains(equipCode))
			{
				equipSet.add(equipCode);
			}
			int paraId = Integer.valueOf(trimData(data[2]));
			if (ignoreParaIds.contains(paraId))
			{
				allIgnoreCount++;
				return;
			}
			HashMap<String, Long> nowDataCount = allDataCount.get(paraId);
			long count = 0;
			if (nowDataCount.containsKey(equipCode))
			{
				count = nowDataCount.get(equipCode);
			}
			count++;
			nowDataCount.put(equipCode, count);
		}
		catch (NumberFormatException e1)
		{
			e1.printStackTrace();
			logger.error(e1.getMessage() + "(ori:)" + string);
			allIgnoreCount++;
			errorCount++;
			return;
		}
	}
	
	private static String trimData(String oriData)
	{
		oriData = oriData.trim();
		oriData = oriData.substring(1, oriData.length() - 1);
		return oriData;
	}
	
	protected static void parseParams(String[] args)
	{
		for (int i = 0; i < args.length; i += 2)
		{
			if (args[i].equals("--csvpath"))
			{
				csvFolder = args[i + 1];
			}
			else if (args[i].equals("--cfsfile"))
			{
				cfsFile = args[i + 1];
			}
		}
		
		logger.info("csv path = " + csvFolder);
		logger.info("cfs file = " + cfsFile);
	}
	
	protected static boolean getCFNames()
	{
		boolean flag = true;
		File file = new File(cfsFile);
		BufferedReader bReader = null;
		String paraIdString = null;
		ArrayList<Integer> cfList = new ArrayList<Integer>();
		try
		{
			bReader = new BufferedReader(new FileReader(file));
			while ((paraIdString = bReader.readLine()) != null)
			{
				paraIdString = paraIdString.trim();
				if (paraIdString.equals(""))
				{
					continue;
				}
				int paraId = Integer.valueOf(paraIdString);
				cfList.add(paraId);
				allDataCount.put(paraId, new HashMap<String, Long>());
			}
			
		}
		catch (IOException e1)
		{
			flag = false;
			logger.error("can not open cf file");
		}
		catch (NumberFormatException e2)
		{
			flag = false;
			logger.error("cf file contains invalid integer");
		}
		finally
		{
			if (flag == false)
			{
				logger.info("get cfs failed!");
			}
			try
			{
				if (bReader != null)
				{
					bReader.close();
				}
			}
			catch (IOException e)
			{
				logger.info(e.getMessage());
			}
		}
		if (flag == true)
		{
			cFS = cfList.toArray(new Integer[0]);
		}
		return flag;
	}
	
	protected static boolean testCsvFoler()
	{
		try
		{
			File file = new File(csvFolder);
			if (file.exists())
			{
				return true;
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		return false;
	}
	
	protected static boolean testCfFile()
	{
		try
		{
			File file = new File(cfsFile);
			if (file.exists())
			{
				return true;
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		return false;
	}
	
	protected static boolean getIgnoreParaIds()
	{
		ignoreParaIds = new HashSet<Integer>();
		ignoreParaIds.add(356);
		return true;
	}
	
}
